home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / PowerMacOberon 1.2 / Source / Elems / FoldElems.Mod (.txt) < prev    next >
Oberon Text  |  1995-08-22  |  14KB  |  363 lines

  1. Syntax10.Scn.Fnt
  2. StampElems
  3. Alloc
  4. 9 Jun 95
  5. Syntax10b.Scn.Fnt
  6. MODULE FoldElems;    (** HM 
  7. IMPORT Display, Oberon, Input, Files, Texts, Viewers, MenuViewers, TextFrames;
  8. CONST
  9.     rightKey = 0; middleKey = 1; leftKey = 2;
  10.     colLeft* = 0; colRight* = 1; expRight* = 2; expLeft* = 3; tempLeft* = 4; findLeft* = 5;    (*fold element mode*)
  11.     leftMode = {colLeft, expLeft, tempLeft, findLeft};
  12.     rightMode = {colRight, expRight};
  13.     tempMode = {tempLeft, findLeft};
  14.     pixel = 10000;
  15.     invisW = 1 * pixel;  (*width of an invisible element*)
  16.     Elem* = POINTER TO ElemDesc;
  17.     ElemDesc* = RECORD (Texts.ElemDesc)
  18.         mode*: SHORTINT;
  19.         hidden*: Texts.Buffer;
  20.         visible*: BOOLEAN
  21.     END;
  22.     CheckProc* = PROCEDURE(e: Texts.Elem): BOOLEAN;
  23.     MarkElem = POINTER TO MarkElemDesc;
  24.     MarkElemDesc = RECORD (Texts.ElemDesc) END;
  25.     FindInfo = RECORD
  26.         found: BOOLEAN;
  27.         text: Texts.Text;
  28.         pos: LONGINT;
  29.         pat: ARRAY 128 OF CHAR;
  30.         len: INTEGER
  31.     END;
  32.     PrepSwitchMsg* = RECORD (Texts.ElemMsg) END;
  33.     elemW-, elemH-: LONGINT;
  34.     w: Texts.Writer;
  35.     inf: FindInfo;
  36.     x0, y0: INTEGER; (*x and y metric of fold characters*)
  37.     Pat: ARRAY 6 OF Display.Pattern; (* x = 0, y = 3, w = 8, h = 9 *)
  38.     icl, icr, iel, ier: ARRAY 4 OF SET;
  39. PROCEDURE NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);    
  40. END NoNotify;
  41. PROCEDURE FindCheck (e: Texts.Elem): BOOLEAN;    
  42. BEGIN RETURN e IS MarkElem
  43. END FindCheck;
  44. PROCEDURE TargetText (): Texts.Text;    
  45.     VAR f: Display.Frame; v: Viewers.Viewer;
  46. BEGIN f := NIL;
  47.     IF Oberon.Par.frame = Oberon.Par.vwr.dsc THEN f := Oberon.Par.frame.next
  48.     ELSE v := Oberon.MarkedViewer();
  49.         IF (v # NIL) & (v.dsc # NIL) THEN f := v.dsc.next END
  50.     END;
  51.     IF (f # NIL) & (f IS TextFrames.Frame) THEN RETURN f(TextFrames.Frame).text
  52.     ELSE RETURN NIL
  53. END TargetText;
  54. PROCEDURE Echo* (t: Texts.Text; on: BOOLEAN);    
  55. BEGIN
  56.     IF on THEN t.notify := TextFrames.NotifyDisplay ELSE t.notify := NoNotify END
  57. END Echo;
  58. PROCEDURE Update (e: Elem);    
  59.     VAR t: Texts.Text; pos: LONGINT;
  60. BEGIN t := Texts.ElemBase(e); pos := Texts.ElemPos(e); t.notify(t, Texts.replace, pos, pos+1)
  61. END Update;
  62. PROCEDURE Twin* (e: Elem): Elem;    
  63.     VAR level, sp: INTEGER; stack: ARRAY 8 OF Elem; r: Texts.Reader; E: Elem;
  64. BEGIN E := NIL; level := 1;
  65.     IF e.mode IN leftMode THEN Texts.OpenReader(r, Texts.ElemBase(e), Texts.ElemPos(e)+1);
  66.         LOOP Texts.ReadElem(r);
  67.             IF r.elem = NIL THEN EXIT
  68.             ELSIF r.elem IS Elem THEN E := r.elem(Elem);
  69.                 IF E.mode IN leftMode THEN INC(level) ELSE DEC(level) END;
  70.                 IF level = 0 THEN EXIT END
  71.             END
  72.         END
  73.     ELSE
  74.         Texts.OpenReader(r, Texts.ElemBase(e), Texts.ElemPos(e));
  75.         LOOP Texts.ReadPrevElem(r);
  76.             IF r.elem = NIL THEN EXIT
  77.             ELSIF r.elem IS Elem THEN E := r.elem(Elem);
  78.                 IF E.mode IN rightMode THEN INC(level) ELSE DEC(level) END;
  79.                 IF level = 0 THEN EXIT END
  80.             END
  81.         END
  82.     END;
  83.     RETURN E
  84. END Twin;
  85. PROCEDURE Switch* (e: Elem);    
  86.     VAR a, b: Elem; apos: LONGINT; t: Texts.Text; buf: Texts.Buffer; prepare: PrepSwitchMsg;
  87. BEGIN
  88.     IF e.mode IN leftMode THEN a := e; b := Twin(a) ELSE b := e; a := Twin(b) END;
  89.     IF a.mode IN tempMode THEN a.mode := expLeft END;
  90.     IF (a # NIL) & (b # NIL) THEN
  91.         a.handle(a, prepare);
  92.         t := Texts.ElemBase(a); apos := Texts.ElemPos(a);
  93.         a.mode := 3 - a.mode; b.mode := 3 - b.mode;
  94.         Texts.Delete(t, apos+1, Texts.ElemPos(b)); Texts.Recall(buf);
  95.         Texts.Insert(t, apos+1, a.hidden); a.hidden := buf;
  96.         Update(a)
  97. END Switch;
  98. PROCEDURE ExpandAll* (t: Texts.Text; from: LONGINT; temporal: BOOLEAN);    
  99.     VAR r: Texts.Reader; E: Elem; res: INTEGER;
  100. BEGIN Texts.OpenReader(r, t, from);
  101.     LOOP Texts.ReadElem(r);
  102.         IF r.elem = NIL THEN EXIT
  103.         ELSIF r.elem IS Elem THEN E := r.elem(Elem);
  104.             IF E.mode = colLeft THEN
  105.                 Switch(E); IF temporal THEN E.mode := tempLeft END;
  106.                 Texts.OpenReader(r, t, Texts.ElemPos(E)+1)
  107.             END
  108.         END
  109. END ExpandAll;
  110. PROCEDURE CollapseAll* (t: Texts.Text; modes: SET);    
  111.     VAR r: Texts.Reader;
  112. BEGIN Texts.OpenReader(r, t, t.len);
  113.     LOOP Texts.ReadPrevElem(r);
  114.         IF r.elem = NIL THEN EXIT
  115.         ELSIF (r.elem IS Elem) & (r.elem(Elem).mode IN modes) THEN Switch(r.elem(Elem))
  116.         END
  117. END CollapseAll;
  118. PROCEDURE FindElem* (t: Texts.Text; pos: LONGINT; P: CheckProc; VAR elem: Texts.Elem);    
  119.     VAR r: Texts.Reader; E: Elem;
  120.     PROCEDURE Inside(buf: Texts.Buffer): BOOLEAN;    
  121.         VAR r: Texts.Reader; t0: Texts.Text; found: BOOLEAN;
  122.     BEGIN t0 := TextFrames.Text(""); Texts.Append(t0, buf); Texts.OpenReader(r, t0, 0); found := FALSE;
  123.         LOOP Texts.ReadElem(r);
  124.             IF r.elem = NIL THEN EXIT
  125.             ELSIF P(r.elem) OR (r.elem IS Elem) & (r.elem(Elem).mode = colLeft) & Inside(r.elem(Elem).hidden) THEN
  126.                 found := TRUE; EXIT
  127.             END
  128.         END;
  129.         Texts.Save(t0, 0, t0.len, buf); RETURN found
  130.     END Inside;
  131. BEGIN Texts.OpenReader(r, t, pos);
  132.     LOOP Texts.ReadElem(r); pos := Texts.Pos(r);
  133.         IF (r.elem = NIL) OR P(r.elem) THEN elem := r.elem; EXIT END;
  134.         IF r.elem IS Elem THEN E := r.elem(Elem);
  135.             IF (E.mode = colLeft) & Inside(E.hidden) THEN
  136.                 Switch(E); E.mode := findLeft; Texts.OpenReader(r, t, pos)
  137.             END
  138.         END
  139. END FindElem;
  140. PROCEDURE FoldHandler* (e: Texts.Elem; VAR m: Texts.ElemMsg);    
  141.     VAR a: Elem; keys: SET; x, y: INTEGER; t: Texts.Text; buf: Texts.Buffer; k, mode: SHORTINT;
  142.         neutralize: Oberon.ControlMsg;
  143. BEGIN
  144.     WITH e: Elem DO
  145.         WITH
  146.             m: Texts.FileMsg DO
  147.                 IF m.id = Texts.load THEN
  148.                     Files.Read(m.r, k); e.mode := k MOD 4; e.visible := e.W > invisW;
  149.                     IF e.mode IN leftMode THEN
  150.                         NEW(e.hidden); Texts.OpenBuf(e.hidden);
  151.                         IF k < 4 THEN (*text not empty*)
  152.                             t := TextFrames.Text("");
  153.                             Texts.Load(m.r, t);
  154.                             Texts.Save(t, 0, t.len, e.hidden)
  155.                         END
  156.                     END
  157.                 ELSE (*Texts.store*)
  158.                     mode := e.mode;
  159.                     IF mode IN tempMode THEN mode := expLeft END;
  160.                     IF (mode IN leftMode) & (e.hidden.len = 0) THEN k := mode +  4 ELSE k := mode END;
  161.                     Files.Write(m.r, k);
  162.                     IF (k < 4)  & (mode IN leftMode) THEN
  163.                         t := TextFrames.Text("");
  164.                         NEW(buf); Texts.OpenBuf(buf); Texts.Copy(e.hidden, buf); Texts.Append(t, buf);
  165.                         Texts.Store(m.r, t)
  166.                     END
  167.                 END
  168.         | m: Texts.CopyMsg DO
  169.                 NEW(a); Texts.CopyElem(e, a);
  170.                 a.mode := e.mode; a.visible := e.visible;
  171.                 IF e.mode IN leftMode THEN
  172.                     NEW(a.hidden); Texts.OpenBuf(a.hidden); Texts.Copy(e.hidden, a.hidden)
  173.                 END;
  174.                 m.e := a
  175.         | m: Texts.IdentifyMsg DO
  176.                 m.mod := "FoldElems"; m.proc := "New"
  177.         | m: TextFrames.DisplayMsg DO
  178.             IF m.prepare THEN
  179.                 IF e.visible THEN e.W := elemW ELSE e.W := invisW END
  180.             ELSIF e.visible THEN
  181.                 Display.CopyPattern(15, Pat[e.mode], m.X0 + x0, m.Y0 + y0, Display.replace)
  182.             END
  183.         | m: TextFrames.TrackMsg DO
  184.                 IF middleKey IN m.keys THEN
  185.                     neutralize.id := Oberon.neutralize; m.frame.handle(m.frame, neutralize);
  186.                     IF e.mode IN tempMode THEN mode := expLeft ELSE mode := e.mode END;
  187.                     Display.CopyPattern(Display.white, Pat[mode], m.X0 + x0, m.Y0 + y0, Display.invert);
  188.                     Display.CopyPattern(Display.white, Pat[3 - mode], m.X0 + x0, m.Y0 + y0, Display.invert);
  189.                     REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys;
  190.                         Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y)
  191.                     UNTIL keys = {};
  192.                     IF m.keys = {middleKey} THEN Switch(e)
  193.                     ELSE
  194.                         Display.CopyPattern(Display.white, Pat[3 - mode], m.X0 + x0, m.Y0 + y0, Display.invert);
  195.                         Display.CopyPattern(Display.white, Pat[mode], m.X0 + x0, m.Y0 + y0, Display.invert)
  196.                     END
  197.                 END
  198.         ELSE
  199.         END
  200. END FoldHandler;
  201. PROCEDURE MarkHandler (e: Texts.Elem; VAR m: Texts.ElemMsg);    
  202.     VAR a: MarkElem;
  203. BEGIN
  204.     IF m IS Texts.CopyMsg THEN NEW(a); Texts.CopyElem(e, a); m(Texts.CopyMsg).e := a END
  205. END MarkHandler;
  206. PROCEDURE Insert*;    
  207.     VAR e: Elem; t: Texts.Text; beg, end, time: LONGINT;
  208. BEGIN
  209.     Oberon.GetSelection(t, beg, end, time);
  210.     IF (time >= 0) & (t IS Texts.Text) THEN
  211.         NEW(e); e.mode := expRight; e.W := elemW; e.H := elemH; e.handle := FoldHandler;
  212.         e.visible := TRUE; Texts.WriteElem(w, e); Texts.Insert(t, end, w.buf);
  213.         NEW(e); e.mode := expLeft; e.W := elemW; e.H := elemH; e.handle := FoldHandler;
  214.         NEW(e.hidden); Texts.OpenBuf(e.hidden); e.visible := TRUE;
  215.         Texts.WriteElem(w, e); Texts.Insert(t, beg, w.buf)
  216. END Insert;
  217. PROCEDURE InsertCollapsed*;    
  218.     VAR e: Elem; t: Texts.Text; beg, end, time: LONGINT;
  219. BEGIN
  220.     Oberon.GetSelection(t, beg, end, time);
  221.     IF (time >= 0) & (t IS Texts.Text) THEN
  222.         NEW(e); e.mode := colRight; e.W := elemW; e.H := elemH; e.handle := FoldHandler;
  223.         e.visible := TRUE; Texts.WriteElem(w, e); Texts.Insert(t, end, w.buf);
  224.         NEW(e); e.mode := colLeft; e.W := elemW; e.H := elemH; e.handle := FoldHandler;
  225.         NEW(e.hidden); Texts.OpenBuf(e.hidden); e.visible := TRUE;
  226.         Texts.WriteElem(w, e); Texts.Insert(t, beg, w.buf)
  227. END InsertCollapsed;
  228. PROCEDURE Marks*;    
  229.     VAR s: Texts.Scanner; t: Texts.Text; beg, end, time: LONGINT; visible: BOOLEAN;
  230.         wt: Texts.Text; r: Texts.Reader;
  231. BEGIN
  232.     wt := TargetText();
  233.     IF wt # NIL THEN
  234.         Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s);
  235.         IF (s.class = Texts.Char) & (s.c = "^") & (s.line = 0) THEN
  236.             Oberon.GetSelection(t, beg, end, time);
  237.             IF time >= 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) END
  238.         END;
  239.         IF (s.class = Texts.Name) & ((s.s = "on") OR (s.s = "off")) THEN visible := s.s = "on";
  240.             Texts.OpenReader(r, wt, 0);
  241.             LOOP Texts.ReadElem(r);
  242.                 IF r.elem = NIL THEN EXIT
  243.                 ELSIF r.elem IS Elem THEN
  244.                     r.elem(Elem).visible := visible;
  245.                     Update(r.elem(Elem))
  246.                 END
  247.             END
  248.         END
  249. END Marks;
  250. PROCEDURE Search*;    
  251.     VAR v: Viewers.Viewer; f: TextFrames.Frame; t: Texts.Text; r: Texts.Reader; beg, end, time, lim: LONGINT;
  252.         i: INTEGER; ch: CHAR; e: Texts.Elem; ntfy: Texts.Notifier; E: MarkElem; m: Oberon.ControlMsg;
  253. BEGIN
  254.     v := Oberon.Par.vwr;
  255.     IF Oberon.Par.frame # v.dsc THEN v := Oberon.FocusViewer END;
  256.     IF (v # NIL) & (v IS MenuViewers.Viewer) & (v.dsc.next IS TextFrames.Frame) THEN
  257.         f := v.dsc.next(TextFrames.Frame);
  258.         inf.text := f.text;
  259.         IF f.hasCar THEN inf.pos := f.carloc.pos; TextFrames.RemoveCaret(f) ELSE inf.pos := 0 END;
  260.         Oberon.GetSelection(t, beg, end, time);
  261.         IF time >= 0 THEN    (*else find again*)
  262.             Texts.OpenReader(r, t, beg); inf.len := 0;
  263.             WHILE beg < end DO Texts.Read(r, inf.pat[inf.len]); INC(inf.len); INC(beg) END;
  264.             inf.pat[inf.len] := 0X;
  265.             m.id := Oberon.neutralize; Viewers.Broadcast(m);
  266.         END;
  267.         IF inf.len > 0 THEN
  268.             Echo(inf.text, FALSE);
  269.             ExpandAll(inf.text, inf.pos, TRUE);
  270.             inf.found := FALSE; lim := inf.text.len - inf.len;
  271.             Texts.OpenReader(r, inf.text, inf.pos);
  272.             LOOP Texts.Read(r, ch);    (*find*)
  273.                 IF inf.pos > lim THEN EXIT
  274.                 ELSIF ch = inf.pat[0] THEN
  275.                     Texts.Read(r, ch); i := 1;
  276.                     WHILE (i < inf.len) & (ch = inf.pat[i]) DO Texts.Read(r, ch); INC(i) END;
  277.                     IF i = inf.len THEN inf.pos := inf.pos + inf.len; inf.found := TRUE; EXIT
  278.                     ELSE INC(inf.pos); Texts.OpenReader(r, inf.text, inf.pos)
  279.                     END
  280.                 ELSE INC(inf.pos)
  281.                 END
  282.             END;
  283.             IF inf.found THEN
  284.                 NEW(E); E.W := 0; E.H := 0; E.handle := MarkHandler;
  285.                 Texts.WriteElem(w, E); Texts.Insert(inf.text, inf.pos, w.buf);
  286.                 CollapseAll(inf.text, {tempLeft}); 
  287.                 Echo(inf.text, TRUE);
  288.                 FindElem(inf.text, 0, FindCheck, e); inf.pos := Texts.ElemPos(e);
  289.                 IF E = e (*FindElem did not expand anything*) THEN Echo(inf.text, FALSE) END;
  290.                 Texts.Delete(inf.text, inf.pos, inf.pos + 1); Echo(inf.text, TRUE);
  291.                 end := TextFrames.Pos(f, f.X + f.W, f.Y);
  292.                 IF (inf.pos < f.org) OR (inf.pos >= end) THEN TextFrames.Show(f, inf.pos - 120) END;
  293.                 TextFrames.SetCaret(f, inf.pos)
  294.             ELSE CollapseAll(inf.text, {tempLeft}); Echo(inf.text, TRUE)
  295.             END
  296.         END
  297. END Search;
  298. PROCEDURE Restore*;
  299.     VAR t: Texts.Text;
  300. BEGIN t := TargetText(); IF t # NIL THEN CollapseAll(t, {findLeft}) END
  301. END Restore;
  302. PROCEDURE Expand*;    
  303.     VAR t: Texts.Text;
  304. BEGIN t := TargetText(); IF t # NIL THEN ExpandAll(t, 0, FALSE) END
  305. END Expand;
  306. PROCEDURE Collapse*;    
  307.     VAR t: Texts.Text;
  308. BEGIN t := TargetText(); IF t # NIL THEN CollapseAll(t, {expLeft, tempLeft, findLeft}) END
  309. END Collapse;
  310. PROCEDURE New*;    
  311.     VAR e: Elem;
  312. BEGIN NEW(e); e.handle := FoldHandler; Texts.new := e
  313. END New;
  314. PROCEDURE Init;    (*for SPARCstatiom, DECstation, RS6000 and PowerMacintosh *)
  315.     VAR img: ARRAY 10 OF SET;
  316. BEGIN
  317.     img[1] := {2};
  318.     img[2] := {2..3};
  319.     img[3] := {2..4};
  320.     img[4] := {2..5};
  321.     img[5] := {2..6};
  322.     img[6] := {2..5};
  323.     img[7] := {2..4};
  324.     img[8] := {2..3};
  325.     img[9] := {2};
  326.     Pat[0]:=Display.NewPattern(img, 8, 9);    (*collapsed left*)
  327.     img[1] := {2};
  328.     img[2] := {2, 3};
  329.     img[3] := {2, 4};
  330.     img[4] := {2, 5};
  331.     img[5] := {2, 6};
  332.     img[6] := {2, 5};
  333.     img[7] := {2, 4};
  334.     img[8] := {2, 3};
  335.     img[9] := {2};
  336.     Pat[3]:=Display.NewPattern(img, 8, 9);    (*expanded left*)
  337.     img[1] := {5};
  338.     img[2] := {4..5};
  339.     img[3] := {3..5};
  340.     img[4] := {2..5};
  341.     img[5] := {1..5};
  342.     img[6] := {2..5};
  343.     img[7] := {3..5};
  344.     img[8] := {4..5};
  345.     img[9] := {5};
  346.     Pat[1]:=Display.NewPattern(img, 8, 9);    (*collapsed right*)
  347.     img[1] := {5};
  348.     img[2] := {4, 5};
  349.     img[3] := {3, 5};
  350.     img[4] := {2, 5};
  351.     img[5] := {1, 5};
  352.     img[6] := {2, 5};
  353.     img[7] := {3, 5};
  354.     img[8] := {4, 5};
  355.     img[9] := {5};
  356.     Pat[2]:=Display.NewPattern(img, 8, 9);    (*expanded right*)
  357.     Pat[4]:=Pat[3]; Pat[5]:=Pat[3];
  358.     inf.len:=0; elemW:=8*LONG(pixel); elemH:=12*LONG(pixel); x0:=0; y0:=3
  359. END Init;
  360. BEGIN
  361.     Init; Texts.OpenWriter(w)
  362. END FoldElems.
  363.